<template>
  <div class="device-data-resource">
    <Alert class="mb-4" type="warning" show-icon :message="t('tb.dataResource.createTip')" />

    <TableHeader>
      <template #headerTop>
        <div class="flex">
          <div class="flex-1">
            <Segmented v-model:value="activeType" :options="typeTabList" @change="handleTypeChange" />
          </div>
          <Space :size="1" class="mx-4">
            <Tooltip :title="t('tb.dataResource.actions.add')">
              <Icon icon="ant-design:plus-outlined" :size="20" class="cursor-pointer" @click="handleAdd" />
            </Tooltip>
            <Tooltip :title="t('tb.dataResource.actions.refresh')">
              <Icon icon="ant-design:redo-outlined" :size="20" class="cursor-pointer" @click="handleRefresh" />
            </Tooltip>
            <Tooltip :title="t('tb.dataResource.actions.search')">
              <Icon
                icon="ant-design:search-outlined"
                :size="20"
                class="cursor-pointer"
                @click="() => (showSearch = !showSearch)"
              />
            </Tooltip>
            <Tooltip :title="t('tb.dataResource.actions.batchDelete')">
              <Icon
                icon="ant-design:delete-outlined"
                :size="20"
                :class="[
                  'cursor-pointer',
                  selectedRowKeys.length === 0 ? 'text-gray-300 cursor-not-allowed' : 'text-red-500',
                ]"
                @click="selectedRowKeys.length > 0 && handleBatchDelete()"
              />
            </Tooltip>
            <template #split>
              <Divider type="vertical" />
            </template>
          </Space>
        </div>
      </template>
    </TableHeader>

    <div v-if="showSearch" class="mb-4">
      <Input
        v-model:value="searchKeyword"
        :placeholder="t('tb.dataResource.searchPlaceholder')"
        allow-clear
      >
        <template #prefix>
          <Icon icon="ant-design:search-outlined" />
        </template>
      </Input>
    </div>

    <BasicTable :loading="loading" :dataSource="filteredResources" @register="registerTable">
      <template #methodColumn="{ record }">
        {{ getMethodLabel(record.method) }}
      </template>
      <template #levelColumn="{ record }">
        {{ getLevelLabel(record.level) }}
      </template>
      <template #tableNameColumn="{ record }">
        {{ record.table_name || record.resource_name || '--' }}
      </template>
    </BasicTable>

    <CreateOrEditDataResourceModal @register="registerModal" @success="handleModalSuccess" />
  </div>
</template>

<script lang="ts" setup>
  import { ref, computed, reactive, watch } from 'vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { Icon } from '/@/components/Icon';
  import { TableHeader, BasicTable, BasicColumn, useTable } from '/@/components/Table';
  import { Segmented, Input, Alert, Space, Tooltip, Divider } from 'ant-design-vue';
  import { useModal } from '/@/components/Modal';
  import { useDebounceFn } from '@vueuse/core';
  import {
    fetchDataResources,
    fetchServiceData,
    deleteDataResource,
    toggleDataResourceStatus,
    type ServiceDataResource,
    type ServiceDataSource,
  } from '/@/api/service/dataSource';
  import CreateOrEditDataResourceModal from './components/CreateOrEditDataResourceModal.vue';

  type ResourceType = 'database' | 'api' | 'txt' | string;
  type DeviceResourceItem = ServiceDataResource & {
    _normalizedType?: ResourceType;
  };

  const props = defineProps<{
    deviceId?: string;
  }>();

  const emit = defineEmits([
    'search',
    'change-type',
    'create-data-resource',
    'edit-resource',
    'start-resource',
    'stop-resource',
    'delete-resource',
  ]);

  const { t } = useI18n();
  const { createConfirm, showMessage } = useMessage();

  const loading = ref(false);
  const resources = ref<DeviceResourceItem[]>([]);
  const dataSources = ref<ServiceDataSource[]>([]);
  const searchKeyword = ref('');
  const debouncedKeyword = ref('');
  const activeType = ref<ResourceType>('database');
  const showSearch = ref(false);
  const selectedRowKeys = ref<string[]>([]);

  const typeTabList = reactive([
    { value: 'database', label: t('tb.dataResource.types.database'), className: 'segment-tab' },
    { value: 'api', label: t('tb.dataResource.types.api'), className: 'segment-tab' },
    { value: 'txt', label: t('tb.dataResource.types.file'), className: 'segment-tab' },
  ]);

  const columns: BasicColumn[] = [
    {
      title: t('tb.dataResource.columns.name'),
      dataIndex: 'resource_name',
      width: 200,
    },
    {
      title: t('tb.dataResource.columns.desc'),
      dataIndex: 'remark',
      width: 220,
      ellipsis: true,
    },
    {
      title: t('tb.dataResource.columns.sourceName'),
      dataIndex: 'data_source_name',
      width: 200,
    },
    {
      title: t('tb.dataResource.columns.sourceId'),
      dataIndex: 'data_source_id',
      width: 200,
    },
    {
      title: t('tb.dataResource.columns.method'),
      dataIndex: 'method',
      width: 140,
      slots: { customRender: 'methodColumn' },
    },
    {
      title: t('tb.dataResource.columns.interval'),
      dataIndex: 'interval',
      width: 140,
    },
    {
      title: t('tb.dataResource.columns.level'),
      dataIndex: 'level',
      width: 120,
      slots: { customRender: 'levelColumn' },
    },
    {
      title: t('tb.dataResource.columns.table'),
      dataIndex: 'table_name',
      width: 200,
      slots: { customRender: 'tableNameColumn' },
    },
  ];

  const actionColumn: BasicColumn = {
    title: t('tb.dataResource.columns.action'),
    width: 240,
    actions: (record: ServiceDataResource) => [
      {
        label: t('tb.dataResource.actions.start'),
        disabled: record.enabled === '1',
        onClick: () => handleToggle(record, 'enable'),
      },
      {
        label: t('tb.dataResource.actions.edit'),
        onClick: () => handleEdit(record),
      },
      {
        label: t('tb.dataResource.actions.stop'),
        disabled: record.enabled !== '1',
        onClick: () => handleToggle(record, 'disable'),
      },
      {
        label: t('tb.dataResource.actions.delete'),
        color: 'error',
        onClick: () => handleDelete(record),
      },
    ],
  };

  const [registerTable] = useTable({
    rowKey: '.name',
    columns,
    actionColumn,
    showTableSetting: false,
    useSearchForm: false,
    pagination: false,
    canResize: true,
    scroll: { x: 1200, y: 520 },
    striped: false, // 禁用斑马纹
    rowSelection: {
      type: 'checkbox',
      onChange: (keys: string[]) => {
        selectedRowKeys.value = keys as string[];
      },
    },
  });

  const [registerModal, { openModal }] = useModal();

  const handleDebounceSearch = useDebounceFn((value: string) => {
    debouncedKeyword.value = value.trim().toLowerCase();
    emit('search', value);
  }, 300);

  watch(
    () => props.deviceId,
    (deviceId) => {
      if (deviceId) {
        fetchResources(deviceId);
        fetchDataSourcesOptions(deviceId);
      } else {
        resources.value = [];
        dataSources.value = [];
      }
    },
    { immediate: true },
  );

  watch(
    () => searchKeyword.value,
    (value) => {
      handleDebounceSearch(value || '');
    },
  );

  function normalizeResourceType(type?: string): ResourceType {
    const value = type?.toLowerCase() || '';
    if (!value) return 'database';
    if (value.includes('api') || value.includes('http')) return 'api';
    if (value.includes('file') || value.includes('txt') || value.includes('csv')) return 'txt';
    if (value.includes('db') || value.includes('sql')) return 'database';
    return value as ResourceType;
  }

  const filteredResources = computed(() => {
    const keyword = debouncedKeyword.value;
    const typeValue = activeType.value?.toString().toLowerCase();
    return resources.value.filter((item) => {
      const currentType = item._normalizedType || normalizeResourceType(item.type);
      const hitType = typeValue ? currentType === typeValue : true;
      if (!hitType) return false;

      if (!keyword) {
        return true;
      }
      const safeKeyword = keyword.toLowerCase();
      const candidates = [
        item.resource_name,
        item.remark,
        item.data_source_name,
        item.data_source_id,
      ]
        .map((field) => field?.toString().toLowerCase() || '')
        .join('||');
      return candidates.includes(safeKeyword);
    });
  });

  function getMethodLabel(method?: string) {
    switch (method) {
      case '0':
        return t('tb.dataResource.methods.local');
      case '1':
        return t('tb.dataResource.methods.remote');
      default:
        return method || '--';
    }
  }

  function getLevelLabel(level?: string | number) {
    const value = level?.toString();
    switch (value) {
      case '0':
        return t('tb.dataResource.level.low');
      case '1':
        return t('tb.dataResource.level.medium');
      case '2':
        return t('tb.dataResource.level.high');
      default:
        return value || '--';
    }
  }

  async function fetchResources(deviceId: string) {
    if (!deviceId) return;
    try {
      loading.value = true;
      const response = await fetchDataResources(deviceId);
      if (response?.data) {
        if (Array.isArray(response.data)) {
          resources.value = response.data.map((item) => ({
            ...item,
            _normalizedType: normalizeResourceType(item.type),
          }));
        } else if (typeof response.data === 'object' && Object.keys(response.data).length === 0) {
          resources.value = [];
        } else {
          resources.value = [];
        }
      } else {
        resources.value = [];
      }
      selectedRowKeys.value = [];
    } catch (error: any) {
      console.error('获取数据资源失败:', error);
      showMessage(error.message || t('tb.dataResource.messages.fetchError'), 'error');
      resources.value = [];
    } finally {
      loading.value = false;
    }
  }

  async function fetchDataSourcesOptions(deviceId: string) {
    try {
      const response = await fetchServiceData<ServiceDataSource>(deviceId, 'source');
      if (response?.data) {
        if (Array.isArray(response.data)) {
          dataSources.value = response.data;
        } else {
          dataSources.value = [];
        }
      } else {
        dataSources.value = [];
      }
    } catch (error: any) {
      console.error('获取数据源列表失败:', error);
      dataSources.value = [];
    }
  }

  function handleTypeChange(value: string | number) {
    const typeValue = value?.toString() as ResourceType;
    activeType.value = typeValue;
    emit('change-type', typeValue);
  }

  function ensureDeviceId(): string | null {
    if (!props.deviceId) {
      showMessage(t('tb.dataResource.messages.deviceMissing'), 'warning');
      return null;
    }
    return props.deviceId;
  }

  function handleAdd() {
    const deviceId = ensureDeviceId();
    if (!deviceId) return;
    emit('create-data-resource');
    openModal(true, {
      isUpdate: false,
      defaultType: activeType.value,
      dataSources: dataSources.value,
      deviceId,
    });
  }

  function handleEdit(record: ServiceDataResource) {
    const deviceId = ensureDeviceId();
    if (!deviceId) return;
    emit('edit-resource', record);
    openModal(true, {
      isUpdate: true,
      record,
      dataSources: dataSources.value,
      deviceId,
    });
  }

  function handleBatchDelete() {
    const deviceId = ensureDeviceId();
    if (!deviceId) {
      return;
    }
    if (selectedRowKeys.value.length === 0) {
      showMessage(t('tb.dataResource.messages.selectResource'), 'warning');
      return;
    }
    const selectedRecords = resources.value.filter((item) => selectedRowKeys.value.includes(item['.name']));
    const names = selectedRecords.map((item) => item['.name']).join(',');

    createConfirm({
      iconType: 'warning',
      title: t('tb.dataResource.actions.batchDeleteConfirm'),
      content: `${t('tb.dataResource.selectedCount')}: ${selectedRowKeys.value.length}`,
      centered: false,
      okText: t('tb.dataResource.actions.batchDelete'),
      okButtonProps: {
        type: 'primary',
        danger: true,
      },
      onOk: async () => {
        try {
          await deleteDataResource(deviceId, names);
          showMessage(t('tb.dataResource.messages.batchDeleteSuccess'), 'success');
          selectedRowKeys.value = [];
          await fetchResources(deviceId);
        } catch (error: any) {
          console.error('批量删除数据资源失败:', error);
          showMessage(error.message || t('tb.dataResource.messages.batchDeleteError'), 'error');
        }
      },
    });
  }

  async function handleRefresh() {
    const deviceId = ensureDeviceId();
    if (!deviceId) return;
    await Promise.all([fetchResources(deviceId), fetchDataSourcesOptions(deviceId)]);
  }

  async function handleToggle(record: ServiceDataResource, batch: 'enable' | 'disable') {
    const deviceId = ensureDeviceId();
    if (!deviceId) return;
    emit(batch === 'enable' ? 'start-resource' : 'stop-resource', record);
    try {
      if (!record['.name']) {
        showMessage(t('tb.dataResource.messages.missingName'), 'warning');
        return;
      }
      await toggleDataResourceStatus(deviceId, record['.name'], batch);
      showMessage(
        batch === 'enable'
          ? t('tb.dataResource.messages.startSuccess')
          : t('tb.dataResource.messages.stopSuccess'),
        'success',
      );
      await fetchResources(deviceId);
    } catch (error: any) {
      console.error('切换数据资源状态失败:', error);
      showMessage(error.message || t('tb.dataResource.messages.toggleError'), 'error');
    }
  }

  function handleDelete(record: ServiceDataResource) {
    emit('delete-resource', record);
    const deviceId = ensureDeviceId();
    if (!deviceId) return;
    createConfirm({
      iconType: 'warning',
      title: t('tb.dataResource.actions.deleteConfirm'),
      content: `${t('tb.dataResource.columns.name')}：${record.resource_name || record['.name']}`,
      okButtonProps: { type: 'primary', danger: true },
      onOk: async () => {
        try {
          await deleteDataResource(deviceId, record['.name']);
          showMessage(t('tb.dataResource.messages.deleteSuccess'), 'success');
          await fetchResources(deviceId);
        } catch (error: any) {
          console.error('删除数据资源失败:', error);
          showMessage(error.message || t('tb.dataResource.messages.deleteError'), 'error');
        }
      },
    });
  }

  async function handleModalSuccess() {
    const deviceId = ensureDeviceId();
    if (deviceId) {
      await fetchResources(deviceId);
    }
    selectedRowKeys.value = [];
  }
</script>

<style lang="less" scoped>
  .device-data-resource {
    :deep(.segment-tab) {
      min-width: 96px;
      text-align: center;
    }
  }
</style>
